package ac.man.cs.afzal.tcm.term_similarities;

import ac.man.cs.afzal.tcm.sql_handler.SQL_Handler_Diseases_Impl;
import ac.man.cs.afzal.tcm.nlp.File_Manager_Impl;
import ac.man.cs.afzal.tcm.nlp.*;

import java.io.*;
import java.util.*;
import java.util.logging.*;

/**
 * Title: Term Classifier
 *
 * @author Hammad Afzal
 * @version 1.0
 * Last Modification Date: 17th Jan, 2013
 */
public class Context_Builder_Diseases_GAD
{

    private String instance_1, instance_2, pattern_1, pattern_2;
    private int number_of_sentences_per_document;

    private String database_url = "database_url";
    private String username = "username";
    private String password = "password";

    private String PARSED_SENTENCES_XML_CORPUS = "PARSED_SENTENCES_XML_CORPUS";
    private String PARSED_SENTENCES_XML_TRAINING = "PARSED_SENTENCES_XML_TRAINING";

    private String MODE = "MODE";

    String[] tables =                
    {
        "Noun_Profiles_diseases_gad", "Verb_Profiles_diseases_gad", "Left_Patterns_diseases_gad", "Right_Patterns_diseases_gad"
    };

    private final String[] stop_word_tags = {"Background","Conclusion","-LRB-","-RRB-","Figure","Result","table","Abstract"};

    private SQL_Handler_Diseases_Impl sql_handler;
    private File_Manager_Impl file_manager = new File_Manager_Impl();
    private String_Manipulator_Impl str_man = new String_Manipulator_Impl();

    public Context_Builder_Diseases_GAD()
    {
        try
        {
            Properties props = new Properties();
            props.load(new FileInputStream("Term_Classification.properties"));

            database_url = props.getProperty(database_url);
            username = props.getProperty(username);
            password = props.getProperty(password);

            PARSED_SENTENCES_XML_TRAINING = props.getProperty(PARSED_SENTENCES_XML_TRAINING);
            PARSED_SENTENCES_XML_CORPUS = props.getProperty(PARSED_SENTENCES_XML_CORPUS);

            MODE = props.getProperty(MODE);
        }
        catch (IOException ex)
        {
            Logger.getLogger(Context_Builder_Impl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void building_contexts_diseases_gad()
    {

        String file_contents = "";
        List<String> docs_not_processed = new ArrayList<String>();

        sql_handler = new SQL_Handler_Diseases_Impl();
        sql_handler.initialize_parameters(database_url, username, password);
        sql_handler.connect_db();
        sql_handler.reset_tables(tables);


        for (String document_name: sql_handler.get_all_corpus_documents())
        {
            int doc_id = sql_handler.get_document_id(document_name);

            File file_document= MODE.equals("Corpus") ? new File(PARSED_SENTENCES_XML_CORPUS + "//" + document_name)
                    : new File(PARSED_SENTENCES_XML_TRAINING + "//" + document_name);

            String[] sentences_per_document = file_document.list();
            try
            {
                number_of_sentences_per_document = sentences_per_document.length;
            }
            catch(Exception ex)
            {
                System.out.println(ex.getStackTrace());
                docs_not_processed.add(file_document.toString());
            }


            for (int i = 0; i < number_of_sentences_per_document; i++)
            {
                String sentence_file_name = sentences_per_document[i];
                File file_sentence = MODE.equals("Corpus") ? new File(PARSED_SENTENCES_XML_CORPUS + "//" + document_name + "//" + sentence_file_name)
                        : new File(PARSED_SENTENCES_XML_TRAINING + "//" + document_name + "//" + sentence_file_name);

                System.out.println("Document being processed : " + file_sentence);
                file_contents = file_manager.fileReader(file_sentence.getAbsoluteFile()).toString();

                String[] str = file_contents.split("MAIN_TERM"); // Splits a sentence where Main term appears, to find its left and right contextual profiles
                process_sentence(str,sentence_file_name,doc_id);
            }
        }
        sql_handler.close_db();

        file_manager.fileWriter(docs_not_processed.toString(), "Docs_Not_Processed due to no parsable sentences");
    }

    private void process_sentence(String[] str, String sentence_file_name, int doc_id)
    {
        int local_sen_id = 0;
        int disease_gad_id = 0;

        if (str.length >= 2)
        {
            Vector<String> vector_vp = new Vector();
            Vector<String> vector_np = new Vector();
            Vector<String> vector_lcp = new Vector();
            Vector<String> vector_lcp1 = new Vector();
            Vector<String> vector_lcp2 = new Vector();
            Vector<String> vector_rcp = new Vector();
            Vector<String> vector_rcp1 = new Vector();
            Vector<String> vector_rcp2 = new Vector(); // Vectors to store contextual nouns, verbs and left & right patterns.


            String sentence_at_left_of_term = str[0];
            String sentence_at_right_of_term = str[1];

            local_sen_id = Integer.parseInt(str_man.strip_string_at_delimiter(sentence_file_name, "__"));
            int sen_id = sql_handler.get_sentence_id_diseases_gad(doc_id, local_sen_id);
            disease_gad_id = sql_handler.get_disease_gad_id(sen_id);

            extract_tags_from_sentence(sentence_at_left_of_term, disease_gad_id, vector_np, vector_vp, vector_lcp1, vector_lcp2, vector_lcp, vector_rcp1,vector_rcp2, vector_rcp,false);
            extract_tags_from_sentence(sentence_at_right_of_term, disease_gad_id, vector_np, vector_vp,vector_lcp1, vector_lcp2, vector_lcp, vector_rcp1,vector_rcp2, vector_rcp,true);
            entry_into_pattern_profile(disease_gad_id, vector_lcp1, vector_lcp2, vector_lcp, vector_rcp1, vector_rcp2, vector_rcp);
        }
    }

    private void extract_tags_from_sentence(String sentence, int disease_id, Vector<String> nouns_vector, Vector<String> verbs_vector,Vector<String> vector_lcp1,Vector<String> vector_lcp2, Vector<String> vector_lcp, Vector<String> vector_rcp1,Vector<String>vector_rcp2, Vector<String> vector_rcp,boolean flag)
    {
        int noun_id = 0;
        int verb_id = 0;

        int noun_profile_id = 0;
        int verb_profile_id = 0;

        int noun_frequency_per_disease_occurrence = 0;
        int verb_frequency_per_disease_occurrence = 0;

        Vector<String> stop_word_tag_list = new Vector(Arrays.asList(stop_word_tags));


        int start_xml_tag_index = 0;
        int end_xml_tag_index = 0;
        int close_xml_tag_index = 0;

        String pos_tag = "";
        String noun_verb_value = "";
        int FLAG_NN = 0; // This flag checks

        while ((start_xml_tag_index = sentence.indexOf("<st_", start_xml_tag_index)) != -1)
        {
            end_xml_tag_index = sentence.indexOf(">", start_xml_tag_index);
            pos_tag = sentence.substring(start_xml_tag_index + 4, end_xml_tag_index);

            if ((pos_tag.equals("NN")) || (pos_tag.equals("NNS")) || (pos_tag.equals("NNPS")) || (pos_tag.equals("NNP")))
            {
                if ((close_xml_tag_index = sentence.indexOf("</st_", end_xml_tag_index + 1)) != -1)
                {
                    noun_verb_value = sentence.substring(end_xml_tag_index + 1, close_xml_tag_index);
                    noun_verb_value = sql_handler.get_stem(noun_verb_value, "noun");

                    noun_id = sql_handler.get_noun_id(noun_verb_value);

                    if (nouns_vector.contains(noun_verb_value.toLowerCase()))
                    {
                        noun_frequency_per_disease_occurrence = sql_handler.get_count_from_disease_profiles("Noun_Profiles_Diseases_GAD", noun_id, disease_id);
                        noun_profile_id = sql_handler.get_id_from_disease_profiles("Noun_Profiles_Diseases_GAD", noun_id, disease_id);
                        ++noun_frequency_per_disease_occurrence;
                        sql_handler.update_table("Noun_Profiles_Diseases_GAD", noun_profile_id, "Freq", Integer.toString(noun_frequency_per_disease_occurrence));
                    }
                    else
                    {
                        if (stop_word_tag_list.contains(noun_verb_value) || (noun_verb_value.length() < 2))
                            ;
                        else
                        {
                            if (noun_verb_value.contains("Term_"))
                            {
                                if(!flag)
                                {
                                    vector_lcp.add("Term");
                                    vector_lcp1.add(noun_verb_value);
                                    vector_lcp2.add("Term:" + noun_verb_value);
                                }
                                else
                                {
                                    vector_rcp.add("Term");
                                    vector_rcp1.add(noun_verb_value);
                                    vector_rcp2.add("Term:" + noun_verb_value);
                                }
                            }
                            else if (FLAG_NN == 1)
                            {
                                nouns_vector.add(noun_verb_value);
                                if (!flag)
                                {
                                    vector_lcp.add("NP");
                                    vector_lcp1.add(noun_verb_value);
                                    vector_lcp2.add("NP:" + noun_verb_value);
                                }
                                else
                                {
                                    vector_rcp.add("NP");
                                    vector_rcp1.add(noun_verb_value);
                                    vector_rcp2.add("NP:" + noun_verb_value);
                                }
                                if (pos_tag.equals("NNP") || pos_tag.equals("NNPS"))
                                {
                                    entry_into_profile(noun_id, noun_verb_value, disease_id, 1, 1); // 1 in last argument represents proper noun
                                }
                                else
                                {
                                    entry_into_profile(noun_id, noun_verb_value, disease_id, 1, 0);
                                }
                            }
                            else
                            {
                                nouns_vector.add(noun_verb_value);
                                if (pos_tag.equals("NNP") || pos_tag.equals("NNPS"))
                                {
                                    entry_into_profile(noun_id, noun_verb_value, disease_id, 1, 1);
                                }
                                else
                                {
                                    entry_into_profile(noun_id, noun_verb_value, disease_id, 1, 0);
                                }
                            }
                        }
                    }
                }
                start_xml_tag_index = start_xml_tag_index + 7;
            }
            else if ((pos_tag.equals("VBZ")) || (pos_tag.equals("VBG"))
                    || (pos_tag.equals("VB")) || (pos_tag.equals("VBN")))
            {
                if ((close_xml_tag_index = sentence.indexOf("</st_", end_xml_tag_index + 1)) != -1)
                {
                    noun_verb_value = sentence.substring(end_xml_tag_index + 1, close_xml_tag_index);
                    noun_verb_value = sql_handler.get_stem(noun_verb_value, "verb");

                    verb_id = sql_handler.get_verb_id(noun_verb_value);

                    if (verbs_vector.contains(noun_verb_value.toLowerCase()))
                    {
                        verb_frequency_per_disease_occurrence = sql_handler.get_count_from_disease_profiles("Verb_Profiles_Diseases_GAD", verb_id, disease_id);
                        verb_profile_id = sql_handler.get_id_from_disease_profiles("Verb_Profiles_Diseases_GAD", verb_id, disease_id);
                        ++verb_frequency_per_disease_occurrence;
                        sql_handler.update_table("Verb_Profiles_Diseases_GAD", verb_profile_id, "Freq", Integer.toString(verb_frequency_per_disease_occurrence));
                    }
                    else
                        if ((noun_verb_value.equals("are")) || (noun_verb_value.length() < 3)
                            || (noun_verb_value.equals("have")) || (noun_verb_value.equals("been")))
                            ;
                        else
                        {
                            entry_into_profile(verb_id, noun_verb_value, disease_id, 2, 0);
                            verbs_vector.add(noun_verb_value);
                            if (!flag)
                            {
                                vector_lcp.add(noun_verb_value);
                                vector_lcp1.add(noun_verb_value);
                                vector_lcp2.add(pos_tag + ":" + noun_verb_value);
                            }
                            else
                            {
                                vector_rcp.add(noun_verb_value);
                                vector_rcp1.add(noun_verb_value);
                                vector_rcp2.add(pos_tag + ":" + noun_verb_value);
                            }
                        }
                }
                start_xml_tag_index = start_xml_tag_index + 7;
            }
            else if (pos_tag.equals("NP")) // deal with Noun Phrase
            {
                if ((close_xml_tag_index = sentence.indexOf("</st_NP", end_xml_tag_index + 1)) != -1)
                {
                    FLAG_NN = 0; // Sets the flag to 0 to indicate the Noun Phrase

                    noun_verb_value = sentence.substring(end_xml_tag_index + 1, close_xml_tag_index);
                    if (noun_verb_value.contains("<st_NP"))
                    {
                        start_xml_tag_index = start_xml_tag_index + 6;
                    }
                    else if ((noun_verb_value.contains("Term_")))
                    {
                        if(!flag)
                        {
                            vector_lcp.add("Term");
                            vector_lcp1.add("Term");
                            vector_lcp2.add("NP:Term");
                        }
                        else
                        {
                            vector_rcp.add("Term");
                            vector_rcp1.add("Term");
                            vector_rcp2.add("NP:Term");
                        }
                        start_xml_tag_index = close_xml_tag_index + 8;
                    }
                    else
                    {
                        String output = str_man.pattern_replacer(noun_verb_value, "<st_(.){0,5}>", " ");
                        output = str_man.pattern_replacer(output, "</st_(.){0,5}>", " ");
                        output = output.replace("  ", " ");
                        output = output.replace("   ", " ");

                        if (!flag)
                        {
                            vector_lcp.add(pos_tag);
                            vector_lcp1.add(output);
                            vector_lcp2.add("NP:" + output);

                        }
                        else
                        {
                            vector_rcp.add(pos_tag);
                            vector_rcp1.add(output);
                            vector_rcp2.add("NP:" + output);

                        }
                        start_xml_tag_index = start_xml_tag_index + 7;
                    }
                }
                else
                {
                    FLAG_NN = 1;
                    start_xml_tag_index = start_xml_tag_index + 6;
                }
            }
            else if (pos_tag.equals("IN")) // deals with the prepositions
            {
                if ((close_xml_tag_index = sentence.indexOf("</st_IN", end_xml_tag_index + 1)) != -1)
                {
                    noun_verb_value = sentence.substring(end_xml_tag_index + 1, close_xml_tag_index);
                    if ((noun_verb_value.contains("Term_")) || (noun_verb_value.contains("<st_")))
                    {
                        start_xml_tag_index = start_xml_tag_index + 6;
                    }
                    else
                    {
                        if (!flag)
                        {
                            vector_lcp.add(noun_verb_value);
                            vector_lcp1.add(noun_verb_value);
                            vector_lcp2.add("PREP:" + noun_verb_value);

                        }
                        else
                        {
                            vector_rcp.add(noun_verb_value);
                            vector_rcp1.add(noun_verb_value);
                            vector_rcp2.add("PREP:" + noun_verb_value);

                        }
                        start_xml_tag_index = start_xml_tag_index + 7;
                    }
                }
                else
                {
                    start_xml_tag_index = start_xml_tag_index + 6;
                }
            }
            else
            {
                start_xml_tag_index = start_xml_tag_index + 7;
            }
        }
    }

    private void entry_into_pattern_profile(int disease_id, Vector<String> vector_lcp1,Vector<String> vector_lcp2, Vector<String> vector_lcp, Vector<String> vector_rcp1,Vector<String>vector_rcp2, Vector<String> vector_rcp)
    {
        /************************ Adding Left Pattern into Table *****************************/
        String[] doc_table =
        {
            "Instance", "Pattern", "Disease_ID", "Gen_Pat", "Instance_1", "Pattern_1", "Instance_2", "Pattern_2"
        };

        String instance = vector_lcp1.toString();
        instance = process_instance(instance);

        String pattern = vector_lcp.toString();
        pattern = process_pattern(pattern);

        String gen_pat = vector_lcp2.toString();
        gen_pat.replaceAll("'", "");

        String[] doc_table_value =
        {
            instance, pattern, Integer.toString(disease_id), gen_pat, instance_1, pattern_1, instance_2, pattern_2
        };
        sql_handler.insert_table("Left_Patterns_Diseases_GAD", doc_table, doc_table_value);

        instance = vector_rcp1.toString();
        instance = process_instance(instance);

        pattern = vector_rcp.toString();
        pattern = process_pattern(pattern);

        gen_pat = vector_rcp2.toString();
        gen_pat.replaceAll("'", "");

        String[] doc_table_value_1 =
        {
            instance, pattern, Integer.toString(disease_id), gen_pat, instance_1, pattern_1, instance_2, pattern_2
        };
        sql_handler.insert_table("Right_Patterns_Diseases_GAD", doc_table, doc_table_value_1);

    }

    private String process_instance(String instance)
    {
        instance = instance.replace("  ", " ");
        instance = instance.replace("  ", " ");
        instance = instance.replace(" ,", ",");
        instance = instance.replace(", ", ",");
        instance = instance.replace("'", "");

        if (instance.contains(","))
        {
            instance_1 = instance.substring(0, instance.lastIndexOf(","));
            if (instance_1.contains(","))
            {
                instance_2 = instance_1.substring(0, instance_1.lastIndexOf(","));
                instance_1 = instance.substring(instance_1.lastIndexOf(",") + 1, instance.length() - 1);

                if (instance_2.contains(","))
                {
                    instance_2 = instance.substring(instance_2.lastIndexOf(",") + 1, instance.length() - 1);
                }
                else
                {
                    instance_2 = instance;
                }
            }
            else
            {
                instance_1 = instance;
                instance_2 = instance;
            }
        }
        else
        {
            instance_1 = "EMPTY";
            instance_2 = "EMPTY";
        }
        instance_1 = str_man.remove_braces_around_string(instance_1);
        instance_2 = str_man.remove_braces_around_string(instance_2);

        return instance;

    }

    private String process_pattern(String pattern)
    {
        if (pattern.contains(","))
        {
            pattern_1 = pattern.substring(0, pattern.lastIndexOf(","));
            if (pattern_1.contains(","))
            {
                pattern_2 = pattern_1.substring(0, pattern_1.lastIndexOf(","));
                pattern_1 = pattern.substring(pattern_1.lastIndexOf(",") + 1, pattern.length() - 1);

                if (pattern_2.contains(","))
                {
                    pattern_2 = pattern.substring(pattern_2.lastIndexOf(",") + 1, pattern.length() - 1);
                }
                else
                {
                    pattern_2 = pattern;
                }
            }
            else
            {
                pattern_1 = pattern;
                pattern_2 = pattern;
            }
        }
        else
        {
            pattern_1 = "EMPTY";
            pattern_2 = "EMPTY";
        }

        pattern_1 = str_man.remove_braces_around_string(pattern_1);
        pattern_2 = str_man.remove_braces_around_string(pattern_2);

        return pattern;
    }

    private void entry_into_profile(int id, String noun_verb_value, int disease_id, int table, int proper_noun)
    {
        if (table == 1)
        {
            if (id == 0)
            {
                String[] doc_table =
                {
                    "Value", "Type"
                };
                String[] doc_table_value =
                {
                    noun_verb_value, Integer.toString(proper_noun)
                };
                sql_handler.insert_table("Nouns", doc_table, doc_table_value);
            }
            id = sql_handler.get_noun_id(noun_verb_value);
            String[] doc_table1 =
            {
                "Disease_ID", "Noun_ID", "Freq"
            };
            String[] doc_table_value1 =
            {
                Integer.toString(disease_id), Integer.toString(id), Integer.toString(1)
            };
            sql_handler.insert_table("Noun_Profiles_Diseases_GAD", doc_table1, doc_table_value1);
        }
        else if (table == 2)
        {
            if (id == 0)
            {
                String[] doc_table =
                {
                    "Value"
                };
                String[] doc_table_value =
                {
                    noun_verb_value
                };
                sql_handler.insert_table("Verbs", doc_table, doc_table_value);
            }
            id = sql_handler.get_verb_id(noun_verb_value);
            String[] doc_table1 =
            {
                "Disease_ID", "Verb_ID", "Freq"
            };
            String[] doc_table_value1 =
            {
                Integer.toString(disease_id), Integer.toString(id), Integer.toString(1)
            };
            sql_handler.insert_table("Verb_Profiles_Diseases_GAD", doc_table1, doc_table_value1);
        }
    }
}